﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
//1.this指针通常隐式存在于类中函数的参数里（一般在第一个参数前）
//2.this中储存的是对应对象的地址，用于在调用函数时找到对应的对象成员
//3.通过计算对象的占用空间可知，this指针并不存在于对应的对象中，
//	事实上，this指针只有在调用类中函数时才会生成（且每次调用都会生成并传递给成员函数），其生命周期和调用的函数的生命周期完全一致，且存在于函数的栈中
//4.this指针的类型为T* const ，即可以通过this来修改其指向的内容，但不可以修改this的指向（T代表类类型）
//5.this指针不能显式出现在函数参数的位置，但可以在其他部分显式使用

//this指针的简单示例
//class dzh1
//{
//public:
//	void  Print(int x = 1, int y = 996)
//	{
//		/*_x = x;
//		_y = y;
//		std::cout << _x << " " << _y << std::endl;*/
//		//上述写法隐式使用了this指针，显式使用的代码如下：
//		this->_x = x;
//		this->_y = y;
//		std::cout << this->_x << " " << this->_y << std::endl;
//	}
//	//一般在命名冲突时需要显式使用this指针
//	int Add(int _x, int _y)
//	{
//		return this->_x + _x + this->_y + _y;//如此种情况，参数名和类中成员名相同
//	}
//
//private:
//	int _x = 0;
//	int _y = 0;
//};
//
//int main()
//{
//	dzh1 a;
//	//a.Print(this, 666, 999);//需要注意的是虽然this指针允许被显式使用，但不可以写到函数参数的位置
//	a.Print(666, 999);//666 999\n
//	return 0;
//}

//this指针的相关例题1：以下代码的运行结果是什么？
//1.编译失败 2.运行错误 3.成功运行
//class dzh1
//{
//public:
//	void  Print(int x, int y)
//	{
//		std::cout << x << " " << y << std::endl;
//	}
//	int _x = 996;
//};
//
//int main()
//{
//	dzh1* pa = nullptr;//将pa赋为空指针
//	pa->Print(1,2);//实际此时没有对象，在此情况下，出现了两个主要疑问：
//				   //首先，这行代码实际上没有造成解引用空指针，
//				   //因为类中的函数不会占用对象的空间，实际在编译类时，就将函数本身和其地址存储在了代码区，
//				   //也就是说，这一步"->"并非是通过pa找函数，而是直接取代码区找函数，因此也就没有解引用pa
//				   // 
//				   //其次，由于没有对象，所以this指针是野指针，但仅仅调用Print函数，
//				   //实际上没有用到对象中的成员变量，也就没有用到this指针，也就没有解引用野指针
//				   //虽然能运行，但属于未定义行为（UB），实际开发中绝对禁止这种写法！
// return 0;
//}
//正确答案：3.成功运行


//this指针的相关例题2：以下代码的运行结果是什么？
//1.编译失败 2.运行错误 3.成功运行
class dzh1
{
public:
	void  Print(int x, int y)
	{
		std::cout << x << " " << y << _x << std::endl;//与上述代码不同，这里用到了_x，说明隐性使用了this指针，因此，解引用了空指针，运行错误
	}
	int _x = 996;
};

int main()
{
	dzh1* pa = nullptr;
	pa->Print(1, 2);//1 2 (进程 36172)已退出，代码为 -1073741819 (0xc0000005)
	return 0;
}
//正确答案：2.运行错误
//我的理解：由于函数没在对象中，所以pa指针找函数地址的话不需要访问该对象（实际不存在）的地址的内容，
//          只需要在代码区就能找到，但如果找变量，就要解引用未分配（因为对象a不存在）的地址了

//函数调用：
//只需类型信息（编译期）
//->仅用于语法作用域解析，无物理内存访问

//数据访问：
//需要对象内存布局（运行时）
//->触发真实的内存解引用

//虚函数例外：
//需要通过对象的虚表指针（vptr）二次寻址，必然解引用

//这种设计既保持了语法一致性（统一用->），又在底层高效实现，充分体现了C++"零开销抽象"的哲学。

